--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tests/frontend/hotPathBugRegressions.test.js 8522a5fd9eee9dd0e2dd6a587fa55fe6a624a9ae (8522a5fd) Text, 4.00 KB
T8b949e// SPDX-License-Identifier: 0BSD
T8b949e/**
* Regression tests for bugs found by exploratory probing of hot paths.
*/
Tff7b72import Tb4b4b4{ Te6edf3describeTb4b4b4, Te6edf3expectTb4b4b4, Te6edf3it Tb4b4b4} Tff7b72from Ta5d6ff"vitest"Tb4b4b4;
Tff7b72import Te6edf3MicronParser Tff7b72from Ta5d6ff"@/js/MicronParser.js"Tb4b4b4;
Tff7b72import Tb4b4b4{ Te6edf3renderNomadHtmlPageTb4b4b4, Te6edf3stripOverlayFromCss Tb4b4b4} Tff7b72from Ta5d6ff"@/js/NomadPageRenderer.js"Tb4b4b4;
Tff7b72import Te6edf3DownloadUtils Tff7b72from Ta5d6ff"@/js/DownloadUtils.js"Tb4b4b4;
Te6edf3describeTb4b4b4(Ta5d6ff"hot-path bug regressions"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3itTb4b4b4(Ta5d6ff"strips absolute full-bleed overlays and rejects svg data images"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3css Tff7b72= Te6edf3stripOverlayFromCssTb4b4b4(Ta5d6ff".x{position:absolute;top:0;left:0;width:100%;height:100%;z-index:9}"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3cssTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:\s*absolute/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3cssTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position:static/Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3svg Tff7b72=
Ta5d6ff"data:image/svg+xml," Tff7b72+
Tffa657encodeURIComponentTb4b4b4(Ta5d6ff'<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"></svg>'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(Ta5d6ff`Ta5d6ff<img src="Tffd700${Te6edf3svgTffd700}Ta5d6ff"><img src="data:image/png;base64,aaa">Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"svg+xml"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"data:image/png"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"strips single-quoted position:fixed overlays"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3MicronParserTb4b4b4.Te6edf3stripOverlayStylesTb4b4b4(Ta5d6ff`Ta5d6ff<div style='position:fixed; color:red'>x</div>Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:\s*fixed/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"color:red"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"strips CSS hex-escaped fixed (fixe\\64) in style blocks"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3stripOverlayFromCssTb4b4b4(Ta5d6ff"x{position:fixe\\64;inset:0}"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/fixe\\64/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:\s*fixed/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"position:static"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"Nomad HTML render neutralises CSS-escaped fixed overlays"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(
Ta5d6ff"<body><style>.x{position:fixe\\64;inset:0;z-index:9}</style><div class=x>y</div></body>"
Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/fixe\\64/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:\s*fixed/Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"download filenames drop path traversal segments"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3expectTb4b4b4(
Te6edf3DownloadUtilsTb4b4b4.Te6edf3parseFilenameFromContentDispositionTb4b4b4(Ta5d6ff'attachment; filename="../../evil.html"'Tb4b4b4, Ta5d6ff"safe.bin"Tb4b4b4)
Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"evil.html"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff"../a/b\\c.txt"Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"c.txt"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff".."Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"download filenames strip CR/LF/NUL"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff"a\r\nb.html"Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"ab.html"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff"a\x00b.bin"Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"ab.bin"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"strips zero-width and soft-hyphen hidden fixed overlays"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3zwsp Tff7b72= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(T79c0ff0x200bTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3shyChar Tff7b72= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(T79c0ff0x00adTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3zw Tff7b72= Te6edf3MicronParserTb4b4b4.Te6edf3stripOverlayStylesTb4b4b4(Ta5d6ff`Ta5d6ff<div style="position:fiTffd700${Te6edf3zwspTffd700}Ta5d6ffxed; color:red">x</div>Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3zwTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:\s*fi/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3zwTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"color:red"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3shy Tff7b72= Te6edf3MicronParserTb4b4b4.Te6edf3stripOverlayStylesTb4b4b4(Ta5d6ff`Ta5d6ff<div style="position:fiTffd700${Te6edf3shyCharTffd700}Ta5d6ffxed">x</div>Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3shyTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:/Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3cssZw Tff7b72= Te6edf3stripOverlayFromCssTb4b4b4(Ta5d6ff`Ta5d6ff.x{position:fiTffd700${Te6edf3zwspTffd700}Ta5d6ffxed;inset:0}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3cssZwTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position\s*:\s*fi/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3cssZwTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/position:static/Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3itTb4b4b4(Ta5d6ff"download filenames strip bidi overrides and Windows reserved names"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3rtl Tff7b72= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(T79c0ff0x202eTb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff`Tffd700${Te6edf3rtlTffd700}Ta5d6ffexe.txtTa5d6ff`Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"exe.txt"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff"CON.txt"Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3DownloadUtilsTb4b4b4.Te6edf3sanitizeDownloadFilenameTb4b4b4(Ta5d6ff"evil.txt..."Tb4b4b4, Ta5d6ff"x.bin"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"evil.txt"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────